// main.go

package main

import (
	"crypto/tls"
	"flag"
	"log"
	"os"
	"os/signal"
	"syscall"

	mqtt "github.com/mochi-mqtt/server/v2"
	"github.com/mochi-mqtt/server/v2/hooks/auth"
	"github.com/mochi-mqtt/server/v2/listeners"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"

	"github.com/gin-gonic/gin"
	"path/filepath"
)

// 全局数据库变量
var DB *gorm.DB

func startGinServer() {
	r := gin.Default()

	// 定义一个路由用于下载文件
	r.GET("/data/:filename", func(c *gin.Context) {
		filename := c.Param("filename")
		// 确定文件路径
		filepath := filepath.Join("./data", filename)
		// 触发文件下载，filename 参数为用户下载时看到的文件名
		c.FileAttachment(filepath, filename)
	})

	// 启动 HTTP 服务器
	if err := r.Run(":8080"); err != nil {
		log.Fatalf("Gin 服务器启动失败: %v", err)
	}
}

// 初始化数据库连接
func initDatabase() {
	var err error
	// 使用你的实际 DSN
	dsn := "Honokahqh:123456@tcp(192.168.1.220:3306)/testdb?charset=utf8mb4&parseTime=True&loc=Local"
	DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		log.Fatalf("连接数据库失败，请检查参数：%v", err)
	}
	log.Println("连接数据库成功！")

	// 自动迁移，创建表
	err = DB.AutoMigrate(&ConnectionLog{}, &SubscribeList{})
	if err != nil {
		log.Fatalf("自动迁移失败：%v", err)
	}
	log.Println("自动迁移成功！")
}

func main() {
	// 初始化数据库
	initDatabase()
	go startGinServer()
	// 定义命令行参数
	tcpAddr := flag.String("tcp", ":1883", "TCP 监听地址")
	tlsTcpAddr := flag.String("tls-tcp", ":8883", "TLS TCP 监听地址")
	wsAddr := flag.String("ws", ":1882", "WebSocket 监听地址")
	tlsWsAddr := flag.String("tls-ws", ":8884", "TLS WebSocket 监听地址")
	infoAddr := flag.String("info", ":8080", "Web 信息仪表盘监听地址")
	flag.Parse()

	// 处理系统信号以优雅关闭服务器
	sigs := make(chan os.Signal, 1)
	done := make(chan bool, 1)
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
	go func() {
		<-sigs
		done <- true
	}()

	// 加载服务器证书和私钥
	cert, err := tls.LoadX509KeyPair("server.crt", "server.key")
	if err != nil {
		log.Fatal("加载证书失败:", err)
	}

	// 配置 TLS（仅服务器证书，无需客户端证书）
	tlsConfig := &tls.Config{
		Certificates: []tls.Certificate{cert},
		MinVersion:   tls.VersionTLS12, // 可选：设置最低 TLS 版本
	}

	// 初始化 MQTT 服务器
	server := mqtt.New(&mqtt.Options{
		InlineClient: true, // 允许使用 inline client
	})

	// 添加认证 Hook（允许所有连接）
	server.AddHook(&auth.AllowHook{}, nil)

	// 配置非 TLS 的 TCP 监听器（如果需要）
	tcp := listeners.NewTCP(listeners.Config{
		ID:      "tcp",
		Address: *tcpAddr,
	})
	if err := server.AddListener(tcp); err != nil {
		log.Fatal("添加 TCP 监听器失败:", err)
	}

	// 配置 TLS 的 TCP 监听器
	tlsTcp := listeners.NewTCP(listeners.Config{
		ID:        "tls-tcp",
		Address:   *tlsTcpAddr,
		TLSConfig: tlsConfig,
	})
	if err := server.AddListener(tlsTcp); err != nil {
		log.Fatal("添加 TLS TCP 监听器失败:", err)
	}

	// 配置非 TLS 的 WebSocket 监听器（如果需要）
	ws := listeners.NewWebsocket(listeners.Config{
		ID:      "ws",
		Address: *wsAddr,
	})
	if err := server.AddListener(ws); err != nil {
		log.Fatal("添加 WebSocket 监听器失败:", err)
	}

	// 配置 TLS 的 WebSocket 监听器
	tlsWs := listeners.NewWebsocket(listeners.Config{
		ID:        "tls-ws",
		Address:   *tlsWsAddr,
		TLSConfig: tlsConfig,
	})
	if err := server.AddListener(tlsWs); err != nil {
		log.Fatal("添加 TLS WebSocket 监听器失败:", err)
	}

	// 配置 HTTP 状态监控监听器（可选，是否需要 TLS 取决于需求）
	stats := listeners.NewHTTPStats(
		listeners.Config{
			ID:      "info",
			Address: *infoAddr,
			// 根据需要，您可以为 stats 监听器配置 TLS
			// TLSConfig: tlsConfig,
		},
		server.Info,
	)
	if err := server.AddListener(stats); err != nil {
		log.Fatal("添加 HTTP Stats 监听器失败:", err)
	}

	ExampleHookA := &ExampleHook{
		DB: DB,
	}
	// Add custom hook (ExampleHook) to the server
	err = server.AddHook(ExampleHookA, &ExampleHookOptions{
		Server: server,
	})

	if err != nil {
		log.Fatal(err)
	}

	// 启动 MQTT 服务器
	go func() {
		if err := server.Serve(); err != nil {
			log.Fatal("启动 MQTT 服务器失败:", err)
		}
	}()

	<-done
	server.Log.Warn("捕获到信号，正在停止...")
	_ = server.Close()
	server.Log.Info("mochi-mqtt 已完全关闭")
}
